package org.bet;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.bet.domain.BioFeatureSet;
import org.bet.utils.PredicateUtils;

public abstract class Assert extends org.junit.Assert{

	public static void assertNotEquals(final Object a, final Object b) {
		assertFalse(a.equals(b));
	}

	public static <T> void assertAllEquals(final T[] a, final T[] b) {
		assertAllEquals(a, b, null, null);
	}

	public static void assertAllEquals(final int[] a, final int[] b) {
		if(ArrayUtils.isEmpty(a) || ArrayUtils.isEmpty(b)){
			assertTrue(ArrayUtils.isEmpty(a) && ArrayUtils.isEmpty(b));
		}
		else{
			assertEquals(a.length, b.length);
	
			for (int i = 0; i < a.length; i++) {
				assertEquals(a[i], b[i]);
			}
		}
	}

	public static<T> void assertAllEquals(final T[] a, final T[] b, final Transformer tfa, final Transformer tfb) {
		if(ArrayUtils.isEmpty(a) || ArrayUtils.isEmpty(b)){
			assertTrue(ArrayUtils.isEmpty(a) && ArrayUtils.isEmpty(b));
		}
		else{
			assertEquals(a.length, b.length);
	
			for (int i = 0; i < a.length; i++) {
				assertEquals(a[i], b[i]);
			}
		}
	}

	public static<T> void assertAllEquals(final Collection<T> a, final Collection<T> b) {
		assertAllEquals(a, b, null, null);

	}

	public static<T> void assertAllEquals(final Collection<T> a, final Collection<T> b, final Transformer tfa, final Transformer tfb) {
		if(isEmptyCollection(a) || isEmptyCollection(b)){
			assertTrue(isEmptyCollection(a) && isEmptyCollection(b));
		}
		else{
			assertEquals(a.size(), b.size());
	
			final Collection<T> ta = tfa != null ? CollectionUtils.collect(a, tfa) : a;
			final Collection<T> tb = tfb != null ? CollectionUtils.collect(b, tfb) : b;
	
			assertTrue(CollectionUtils.isEqualCollection(ta, tb));
		}
	}
	
	public static void assertAllTrue(Collection c, Predicate predicate) {

		assertTrue(CollectionUtils.countMatches(c, PredicateUtils
				.notPredicate(predicate)) <= 0);
	}

	public static void assertAllTrue(Object[] a, Predicate predicate) {
		assertAllTrue(Arrays.asList(a), predicate);
	}

	public static void assertEmtpy(String s) {
		assertTrue(StringUtils.isEmpty(s));
	}

	public static void assertEmpty(Collection c) {
		assertTrue(isEmptyCollection(c));
	}


	public static void assertEmpty(Object[] a) {
		assertTrue(ArrayUtils.isEmpty(a));
	}

	public static void assertEmpty(Map m) {
		assertTrue(isEmptyMap(m));
	}
	

	public static void assertAllNotNull(Object[] objArr) {
		assertNotNull(objArr);
		for(Object obj: objArr){
			assertNotNull(obj);
		}
	}

	public static void assertNotEmpty(String s) {
		assertFalse(StringUtils.isEmpty(s));
	}

	public static void assertNotEmpty(Collection c) {
		assertFalse(isEmptyCollection(c));
	}

	public static void assertNotEmpty(Object[] a) {
		assertFalse(ArrayUtils.isEmpty(a));
	}

	public static void assertNotEmpty(Map m) {
		assertFalse(isEmptyMap(m));
	}

	public static void assertNullSafeEquals(Object o1, Object o2) {
		if(o1 == null){
			assertTrue(o2 == null);
		}
		else{
			assertEquals(o1, o2);
		}
	}

	public static<T, V> void assertMapEquals(final Map<T, V> a, final Map<T, V> b){
		if(isEmptyMap(a) || isEmptyMap(b)){
			assertTrue(isEmptyMap(a) && isEmptyMap(b));
		}
		else{
			assertEquals(a.size(), b.size());
	
			for(T key : a.keySet()){
				assertEquals(a.get(key), b.get(key));
			}
			
		}
	}

	public static void assertEqualObjectProperties(BioFeatureSet expected, BioFeatureSet actual, String[] propertyNames) {
		Predicate predicate = PredicateUtils.equalPropertiesPredicate(expected, propertyNames);
		assertTrue(predicate.evaluate(actual));
	}

	
	private static boolean isEmptyCollection(Collection c) {
		return c == null || c.size() == 0;
	}
	
	private static boolean isEmptyMap(Map m) {
		// TODO Auto-generated method stub
		return m == null || m.size() == 0;
	}

}